package org.flexthinker.binding.form.support
{
    import mx.collections.ArrayCollection;

    import org.flexthinker.binding.value.ValueModel;
    import org.flexthinker.binding.value.support.BufferedCollectionValueModel;
    import org.flexthinker.binding.value.support.BufferedValueModel;
    import org.flexthinker.binding.value.support.MockBean;

    import org.flexthinker.binding.value.support.PropertyChangeListenerCounter;
    import org.flexthinker.binding.value.support.ValueHolder;
    import org.hamcrest.assertThat;
    import org.hamcrest.object.equalTo;

    /**
     *
     */
    public class AbstractFormModelTest
    {
        private var fm:AbstractFormModel;

        private var bean:MockBean;

        public function AbstractFormModelTest()
        {
        }

        [Before]
        public function setUp():void
        {
            bean = new MockBean();
            fm = new AbstractFormModel(bean, true);
        }

        [Test]
        public function testGetFieldNames():void
        {
            fm.add("bindableProperty");
            assertThat("getFieldNames is wrong [1]", fm.getFieldNames().length, equalTo(1));
            fm.add("bindablePropertyWithCustomEvent");
            assertThat("getFieldNames is wrong [2]", fm.getFieldNames().length, equalTo(2));

            assertThat("getFieldNames has incorrect values on [0]", fm.getFieldNames()[0], equalTo("bindableProperty"));
        }

        [Test]
        public function testFormObjectInitializationAndCommit():void
        {
            bean.bindableProperty = "STRING PROP";
            assertThat("formObject is wrong", fm.getFormObject(), equalTo(bean));
            var vm1:ValueModel = fm.add("bindableProperty");
            assertThat("valueModel for bean's property should contain the same value", vm1.getValue(),
                    equalTo(bean.bindableProperty));

            fm.getValueModel("bindableProperty").setValue("NEW STRING PROP");
            assertThat("bean's property should NOT update according to buffered valueModel automatically",
                    bean.bindableProperty,
                    equalTo("STRING PROP"));

            fm.commit();
            assertThat("bean's prop should update on form's BufferedValueModel.commit", vm1.getValue(),
                    equalTo(bean.bindableProperty));
        }

        [Test]
        public function testNewFormObjectResetsOldFormObject():void
        {
            var listener:PropertyChangeListenerCounter = new PropertyChangeListenerCounter();
            fm.getValueModel("simpleString").addValueChangeListener(listener);

            var newBean:MockBean = new MockBean();
            newBean.simpleString = "ABC";

            bean.simpleString = "123";
            assertThat("formObject is wrong", fm.getFormObject(), equalTo(bean));
            var vm1:ValueModel = fm.getValueModel("simpleString");
            vm1.setValue("abc");

            assertThat("Change listener should be called", listener.counter, equalTo(2));

            assertThat("value model should contain the modified value", fm.getValueModel("simpleString").getValue(),
                    equalTo('abc'));
            fm.setFormObject(newBean);

            assertThat("Change listener should be called after setting new formObject",
                    listener.counter, equalTo(3));
            assertThat("setting a New FormObject should revert all ValueModels to the new FormObject values",
                    fm.getValueModel("simpleString").getValue(),
                    equalTo('ABC'));
        }

        [Test]
        public function testNEwFormObjectResetsOldFormObjectWithList():void
        {
            var listener:PropertyChangeListenerCounter = new PropertyChangeListenerCounter();
            fm.addValueModelFor("simpleList", new BufferedCollectionValueModel(new ValueHolder(bean, "simpleList"), ArrayCollection));
            fm.getValueModel("simpleList").addValueChangeListener(listener);

            var newBean:MockBean = new MockBean();
            newBean.simpleList = new ArrayCollection( ["A", "B", "C"] );

            bean.simpleList = new ArrayCollection( [1, 2, 3] );
            assertThat("formObject is wrong", fm.getFormObject(), equalTo(bean));
            var vm1:ValueModel = fm.getValueModel("simpleList");
            vm1.setValue(new ArrayCollection(['a','b', 'c']));

            assertThat("Change listener should be called", listener.counter, equalTo(2));

            assertThat("value model should contain the modified value",
                    fm.getValueModel("simpleList").equals( new ArrayCollection(['a','b','c'])),
                    equalTo(true));
            fm.setFormObject(newBean);

            assertThat("Change listener should be called after setting new formObject",
                    listener.counter, equalTo(3));
            assertThat("setting a New FormObject should revert all ValueModels to the new FormObject values",
                    fm.getValueModel("simpleList").equals( newBean.simpleList ),
                    equalTo(true));
        }


    }
}